package cn.cloud.all.security.oauth2.client.token;

import cn.cloud.all.security.core.Authentication;
import cn.cloud.all.security.oauth2.common.util.OAuth2Utils;
import cn.cloud.all.security.oauth2.resource.OAuth2ProtectedResourceDetails;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Basic key generator taking into account the client id, scope and username (principal name) if they exist.
 */
public class DefaultClientKeyGenerator implements ClientKeyGenerator {

    private static final String CLIENT_ID = "client_id";

    private static final String SCOPE = "scope";

    private static final String USERNAME = "username";

    public String extractKey(OAuth2ProtectedResourceDetails resource, Authentication authentication) {
        Map<String, String> values = new LinkedHashMap<>();
        if (authentication != null) {
            values.put(USERNAME, authentication.getName());
        }
        values.put(CLIENT_ID, resource.getClientId());
        if (resource.getScope() != null) {
            values.put(SCOPE, OAuth2Utils.formatParameterList(resource.getScope()));
        }
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("MD5 algorithm not available.  Fatal (should be in the JDK).");
        }

        byte[] bytes = digest.digest(values.toString().getBytes(StandardCharsets.UTF_8));
        return String.format("%032x", new BigInteger(1, bytes));
    }
}
